flowboxchild: Derive from GtkWidget
authorMatthias Clasen <mclasen@redhat.com>
Sun, 3 May 2020 00:53:40 +0000 (20:53 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Tue, 5 May 2020 02:53:08 +0000 (22:53 -0400)
We want to remove GtkBin and GtkContainer as they don't
provide much useful functionality anymore.

See #2681

demos/gtk-demo/sliding_puzzle.c
docs/reference/gtk/gtk4-sections.txt
gtk/a11y/gtkflowboxchildaccessible.c
gtk/gtkemojichooser.c
gtk/gtkflowbox.c
gtk/gtkflowbox.h
tests/testflowbox.c

index 03ac047e6aaf7b6f7bc914873cee969523520eaa..b564e200b5ff9889fbaa03187c2afeec46adf15f 100644 (file)
@@ -367,10 +367,11 @@ reconfigure (void)
       child = selected->data;
       g_list_free (selected);
     }
-  image = gtk_bin_get_child (GTK_BIN (child));
+
+  image = gtk_flow_box_child_get_child (GTK_FLOW_BOX_CHILD (child));
   puzzle = gtk_image_get_paintable (GTK_IMAGE (image));
 
-  start_puzzle (puzzle); 
+  start_puzzle (puzzle);
   popover = gtk_widget_get_ancestor (size_spin, GTK_TYPE_POPOVER);
   gtk_popover_popdown (GTK_POPOVER (popover));
   grid = gtk_aspect_frame_get_child (GTK_ASPECT_FRAME (frame));
index fa46fe3ca82df90007020355bb7151d030ac396c..cd27f991af0e45f2420b1a9eee2c580455c07631 100644 (file)
@@ -5752,6 +5752,8 @@ gtk_flow_box_bind_model
 <SUBSECTION GtkFlowBoxChild>
 GtkFlowBoxChild
 gtk_flow_box_child_new
+gtk_flow_box_child_set_child
+gtk_flow_box_child_get_child
 gtk_flow_box_child_get_index
 gtk_flow_box_child_is_selected
 gtk_flow_box_child_changed
index 2476f97ab09c1700c3dbdcf1d5b8450c8fa4d870..794c4f5ee3665e99ab1d8836631f3bfcaa5d212e 100644 (file)
@@ -22,7 +22,7 @@
 #include "gtk/gtkflowbox.h"
 
 
-G_DEFINE_TYPE (GtkFlowBoxChildAccessible, gtk_flow_box_child_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE)
+G_DEFINE_TYPE (GtkFlowBoxChildAccessible, gtk_flow_box_child_accessible, GTK_TYPE_WIDGET_ACCESSIBLE)
 
 static void
 gtk_flow_box_child_accessible_init (GtkFlowBoxChildAccessible *accessible)
index eee1ac793455f777ac0ca58c019624b260c7aac9..89479f5ca5d42213cae7acde6406c2d87e9a5998 100644 (file)
@@ -372,7 +372,7 @@ emoji_activated (GtkFlowBox      *box,
 
   gtk_popover_popdown (GTK_POPOVER (chooser));
 
-  label = gtk_bin_get_child (GTK_BIN (child));
+  label = gtk_flow_box_child_get_child (child);
   text = g_strdup (gtk_label_get_label (GTK_LABEL (label)));
 
   item = (GVariant*) g_object_get_data (G_OBJECT (child), "emoji-data");
@@ -542,7 +542,7 @@ add_emoji (GtkWidget    *box,
   if (modifier != 0)
     g_object_set_data (G_OBJECT (child), "modifier", GUINT_TO_POINTER (modifier));
 
-  gtk_container_add (GTK_CONTAINER (child), label);
+  gtk_flow_box_child_set_child (GTK_FLOW_BOX_CHILD (child), label);
   gtk_flow_box_insert (GTK_FLOW_BOX (box), child, prepend ? 0 : -1);
 }
 
index e0f0a6131775ffc08826925294e8631b0260065e..98d66f18ed65eedd75381a26ef33fde9ff53ac38 100644 (file)
@@ -79,6 +79,8 @@
 #include "gtkflowboxprivate.h"
 
 #include "gtkadjustment.h"
+#include "gtkbinlayout.h"
+#include "gtkbuildable.h"
 #include "gtkcsscolorvalueprivate.h"
 #include "gtkcssnodeprivate.h"
 #include "gtkgesturedrag.h"
 
 #include "a11y/gtkflowboxaccessibleprivate.h"
 #include "a11y/gtkflowboxchildaccessible.h"
-
 /* Forward declarations and utilities {{{1 */
 
 static void gtk_flow_box_update_cursor       (GtkFlowBox      *box,
@@ -256,16 +258,26 @@ enum {
 
 static guint child_signals[CHILD_LAST_SIGNAL] = { 0 };
 
+enum {
+  PROP_CHILD = 1
+};
+
 typedef struct _GtkFlowBoxChildPrivate GtkFlowBoxChildPrivate;
 struct _GtkFlowBoxChildPrivate
 {
+  GtkWidget     *child;
   GSequenceIter *iter;
   gboolean       selected;
 };
 
 #define CHILD_PRIV(child) ((GtkFlowBoxChildPrivate*)gtk_flow_box_child_get_instance_private ((GtkFlowBoxChild*)(child)))
 
-G_DEFINE_TYPE_WITH_PRIVATE (GtkFlowBoxChild, gtk_flow_box_child, GTK_TYPE_BIN)
+static void gtk_flow_box_child_buildable_iface_init (GtkBuildableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkFlowBoxChild, gtk_flow_box_child, GTK_TYPE_WIDGET,
+                         G_ADD_PRIVATE (GtkFlowBoxChild)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                                gtk_flow_box_child_buildable_iface_init))
 
 /* Internal API {{{2 */
 
@@ -291,14 +303,36 @@ gtk_flow_box_child_set_focus (GtkFlowBoxChild *child)
 
 /* GtkWidget implementation {{{2 */
 
+static GtkBuildableIface *parent_child_buildable_iface;
+
+static void
+gtk_flow_box_child_buildable_add_child (GtkBuildable *buildable,
+                                        GtkBuilder   *builder,
+                                        GObject      *child,
+                                        const gchar  *type)
+{
+  if (GTK_IS_WIDGET (child))
+    gtk_flow_box_child_set_child (GTK_FLOW_BOX_CHILD (buildable), GTK_WIDGET (child));
+  else
+    parent_child_buildable_iface->add_child (buildable, builder, child, type);
+}
+
+static void
+gtk_flow_box_child_buildable_iface_init (GtkBuildableIface *iface)
+{
+  parent_child_buildable_iface = g_type_interface_peek_parent (iface);
+
+  iface->add_child = gtk_flow_box_child_buildable_add_child;
+}
+
 static gboolean
 gtk_flow_box_child_focus (GtkWidget        *widget,
                           GtkDirectionType  direction)
 {
+  GtkFlowBoxChild *self = GTK_FLOW_BOX_CHILD (widget);
+  GtkFlowBoxChildPrivate *priv = CHILD_PRIV (self);
+  GtkWidget *child = priv->child;
   gboolean had_focus = FALSE;
-  GtkWidget *child;
-
-  child = gtk_bin_get_child (GTK_BIN (widget));
 
   /* Without "can-focus" flag try to pass the focus to the child immediately */
   if (!gtk_widget_get_can_focus (widget))
@@ -384,6 +418,77 @@ gtk_flow_box_child_get_request_mode (GtkWidget *widget)
     return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
 }
 
+static void
+gtk_flow_box_child_dispose (GObject *object)
+{
+  GtkFlowBoxChild *self = GTK_FLOW_BOX_CHILD (object);
+  GtkFlowBoxChildPrivate *priv = CHILD_PRIV (self);
+
+  g_clear_pointer (&priv->child, gtk_widget_unparent);
+
+  G_OBJECT_CLASS (gtk_flow_box_child_parent_class)->dispose (object);
+}
+
+static void
+gtk_flow_box_child_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  GtkFlowBoxChild *self = GTK_FLOW_BOX_CHILD (object);
+
+  switch (prop_id)
+    {
+    case PROP_CHILD:
+      g_value_set_object (value, gtk_flow_box_child_get_child (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_flow_box_child_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  GtkFlowBoxChild *self = GTK_FLOW_BOX_CHILD (object);
+
+  switch (prop_id)
+    {
+    case PROP_CHILD:
+      gtk_flow_box_child_set_child (self, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_flow_box_child_compute_expand (GtkWidget *widget,
+                                   gboolean  *hexpand,
+                                   gboolean  *vexpand)
+{
+  GtkFlowBoxChild *self = GTK_FLOW_BOX_CHILD (widget);
+  GtkFlowBoxChildPrivate *priv = CHILD_PRIV (self);
+
+  if (priv->child)
+    {
+      *hexpand = gtk_widget_compute_expand (priv->child, GTK_ORIENTATION_HORIZONTAL);
+      *vexpand = gtk_widget_compute_expand (priv->child, GTK_ORIENTATION_VERTICAL);
+    }
+  else
+    {
+      *hexpand = FALSE;
+      *vexpand = FALSE;
+    }
+}
+
 /* GObject implementation {{{2 */
 
 static void
@@ -392,11 +497,25 @@ gtk_flow_box_child_class_init (GtkFlowBoxChildClass *class)
   GObjectClass *object_class = G_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
 
+  object_class->dispose = gtk_flow_box_child_dispose;
+  object_class->get_property = gtk_flow_box_child_get_property;
+  object_class->set_property = gtk_flow_box_child_set_property;
+
   widget_class->get_request_mode = gtk_flow_box_child_get_request_mode;
+  widget_class->compute_expand = gtk_flow_box_child_compute_expand;
   widget_class->focus = gtk_flow_box_child_focus;
+  widget_class->grab_focus = gtk_widget_grab_focus_none;
 
   class->activate = gtk_flow_box_child_activate;
 
+  g_object_class_install_property (object_class,
+                                   PROP_CHILD,
+                                   g_param_spec_object ("child",
+                                                        P_("Child"),
+                                                        P_("The child widget"),
+                                                        GTK_TYPE_WIDGET,
+                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
   /**
    * GtkFlowBoxChild::activate:
    * @child: The child on which the signal is emitted
@@ -419,6 +538,7 @@ gtk_flow_box_child_class_init (GtkFlowBoxChildClass *class)
                   G_TYPE_NONE, 0);
   widget_class->activate_signal = child_signals[CHILD_ACTIVATE];
 
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
   gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_LIST_ITEM);
   gtk_widget_class_set_css_name (widget_class, I_("flowboxchild"));
 }
@@ -427,7 +547,7 @@ static void
 gtk_flow_box_child_init (GtkFlowBoxChild *child)
 {
 }
-
 /* Public API {{{2 */
 
 /**
@@ -444,6 +564,43 @@ gtk_flow_box_child_new (void)
   return g_object_new (GTK_TYPE_FLOW_BOX_CHILD, NULL);
 }
 
+/**
+ * gtk_flow_box_child_set_child:
+ * @self: a #GtkFlowBoxChild
+ * @child: (allow-none): the child widget
+ *
+ * Sets the child widget of @self.
+ */
+void
+gtk_flow_box_child_set_child (GtkFlowBoxChild *self,
+                              GtkWidget       *child)
+{
+  GtkFlowBoxChildPrivate *priv = CHILD_PRIV (self);
+
+  g_clear_pointer (&priv->child, gtk_widget_unparent);
+
+  priv->child = child;
+  if (child)
+    gtk_widget_set_parent (child, GTK_WIDGET (self));
+  g_object_notify (G_OBJECT (self), "child");
+}
+
+/**
+ * gtk_flow_box_child_get_child:
+ * @self: a #GtkFlowBoxChild
+ *
+ * Gets the child widget of @self.
+ *
+ * Returns: (nullable) (transfer none): the child widget of @self
+ */
+GtkWidget *
+gtk_flow_box_child_get_child (GtkFlowBoxChild *self)
+{
+  GtkFlowBoxChildPrivate *priv = CHILD_PRIV (self);
+
+  return priv->child;
+}
+
 /**
  * gtk_flow_box_child_get_index:
  * @child: a #GtkFlowBoxChild
@@ -3198,7 +3355,7 @@ gtk_flow_box_move_cursor (GtkFlowBox      *box,
     {
       GtkWidget *subchild;
 
-      subchild = gtk_bin_get_child (GTK_BIN (child));
+      subchild = gtk_flow_box_child_get_child (GTK_FLOW_BOX_CHILD (child));
       if (subchild)
         {
           GtkDirectionType direction = count < 0 ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD;
@@ -3853,8 +4010,7 @@ gtk_flow_box_insert (GtkFlowBox *box,
   else
     {
       child = GTK_FLOW_BOX_CHILD (gtk_flow_box_child_new ());
-      gtk_widget_show (GTK_WIDGET (child));
-      gtk_container_add (GTK_CONTAINER (child), widget);
+      gtk_flow_box_child_set_child (child, widget);
     }
 
   if (priv->sort_func != NULL)
index ad1172d0e1e5c603df6df919e50520614a001076..9b1729490d4307d75279b0f0117c30eeff7595ba 100644 (file)
@@ -29,7 +29,7 @@
 #error "Only <gtk/gtk.h> can be included directly."
 #endif
 
-#include <gtk/gtkbin.h>
+#include <gtk/gtkcontainer.h>
 
 G_BEGIN_DECLS
 
@@ -51,12 +51,12 @@ typedef struct _GtkFlowBoxChildClass  GtkFlowBoxChildClass;
 
 struct _GtkFlowBoxChild
 {
-  GtkBin parent_instance;
+  GtkWidget parent_instance;
 };
 
 struct _GtkFlowBoxChildClass
 {
-  GtkBinClass parent_class;
+  GtkWidgetClass parent_class;
 
   void (* activate) (GtkFlowBoxChild *child);
 
@@ -80,6 +80,13 @@ GDK_AVAILABLE_IN_ALL
 GType                 gtk_flow_box_child_get_type            (void) G_GNUC_CONST;
 GDK_AVAILABLE_IN_ALL
 GtkWidget*            gtk_flow_box_child_new                 (void);
+
+GDK_AVAILABLE_IN_ALL
+void                  gtk_flow_box_child_set_child          (GtkFlowBoxChild *self,
+                                                             GtkWidget       *child);
+GDK_AVAILABLE_IN_ALL
+GtkWidget *           gtk_flow_box_child_get_child          (GtkFlowBoxChild *self);
+
 GDK_AVAILABLE_IN_ALL
 gint                  gtk_flow_box_child_get_index           (GtkFlowBoxChild *child);
 GDK_AVAILABLE_IN_ALL
index 30ae1c0b90ebf817f5723e568023c3944bf0d14d..f44cbed2d9a72077db6c1d425996abd77f754aba 100644 (file)
@@ -304,7 +304,7 @@ on_child_activated (GtkFlowBox *self,
                     GtkWidget  *child)
 {
   const char *id;
-  id = g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (child))), "id");
+  id = g_object_get_data (G_OBJECT (gtk_flow_box_child_get_child (GTK_FLOW_BOX_CHILD (child))), "id");
   g_message ("Child activated %p: %s", child, id);
 }
 
@@ -316,7 +316,7 @@ selection_foreach (GtkFlowBox      *self,
   const char *id;
   GtkWidget *child;
 
-  child = gtk_bin_get_child (GTK_BIN (child_info));
+  child = gtk_flow_box_child_get_child (child_info);
   id = g_object_get_data (G_OBJECT (child), "id");
   g_message ("Child selected %p: %s", child, id);
 }
@@ -357,8 +357,8 @@ sort_func (GtkFlowBoxChild *a,
 {
   gchar *ida, *idb;
 
-  ida = (gchar *)g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (a))), "id");
-  idb = (gchar *)g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (b))), "id");
+  ida = (gchar *)g_object_get_data (G_OBJECT (gtk_flow_box_child_get_child (a)), "id");
+  idb = (gchar *)g_object_get_data (G_OBJECT (gtk_flow_box_child_get_child (b)), "id");
   return g_strcmp0 (ida, idb);
 }